package com.cskaoyan.javase.oop1._2reference;
/**
 * 引用数据类型的全新理解:
 *
 * 我们第一次认识和了解引用数据类型是在数组这一章节
 * 我们通过JVM内存模型图和数组的初始化过程，知道：
 * 一个引用数据类型变量，分为两个部分：
 *      1.在栈上创建引用，它是一个局部变量。
 *      2.在堆上开辟空间，创建对象。(堆上对象中的元素具有默认初始化,具有默认值)
 * 栈上的引用通过存储堆上对象的地址和对象产生联系。
 * 对象是引用数据类型的实质，但我们只能通过栈上引用间接访问堆上对象。
 * 现在，我们已经学习过对象与类的知识点了，是时候进一步或者换一个角度去了解引用数据类型了。
 *
 * 像数组那样理解引用数据类型，虽然看到了引用数据类型的实质
 *      但也把基本数据类型和引用数据类型完全割裂了。
 * 这两种数据类型当然不可能是完全没有关系的了！
 * 所以，我们需要让它们重新产生联系起来！
 *
 * 先回顾一下，在Java基础语法部分，我们给出的数据类型的概念/定义：
 * 数据类型: 表示的是一组数据的集合，和基于该数据集合的一组合法操作。
 *      数据 + 操作
 * 这个定义套在基本数据类型上，实在再合适不过了。
 *      比如int类型，它的取值范围是固定的，有限的
 *      能够做的操作（加减乘除等）也是被限制的。
 *
 * 那么这个定义能不能套在引用数据类型中呢？能否用数据类型的概念来统一基本数据类型和引用数据类型呢？
 * 接下来我们需要分析一下，这个问题。
 * 在上一节类的定义中，类中的成员包括：
 *        1.成员变量
 *        2.成员方法
 * 成员变量本质上就是数据，成员方法本质上就是操作，那么假设做以下类比：
 *        1.数据的集合： 类中成员变量的集合
 *        2.操作的集合： 类中成员方法的集合
 * 于是，就可以做出以下总结：
 * 一个类的定义，实际上就是定义了一种全新的数据类型，一种自定义的数据类型。
 * 这种完全不同于基本数据类型的数据类型，我们称之为"引用数据类型"。
 * 注：当然引用数据类型不仅仅包括类，但大体上上述说法是没问题的。
 *
 *
 * 当我们在程序中使用一个基本数据类型时，
 * 由于基本数据类型是JVM当中已经预先定义好的（所以基本数据类型叫"内置数据类型"）
 * JVM可以清楚的知道这个基本数据类型变量在内存中的存储方式（占用空间大小、结构等等）
 * JVM能够正常开辟空间，正常给变量初始化赋值。
 *
 * 但是对于引用数据类型而言,它是一种自定义的数据类型,比如一个类需要创建对象,
 * 那么JVM怎么知道这个引用数据类型,类当中,有哪些成员变量,哪些成员方法呢?
 *
 * 所以JVM在使用一个类之前(比如创建类的对象),需要一个了解,认识该类型的过程
 * 这个过程称之为"类加载(class load)"
 * 关于类加载,我们了解以下几点:
 *      1.类加载的项目流程,及每个步骤的用途,以后课程中会详细了解,今天暂且不谈,只做最基本了解.
 *      2.类加载是通过将某个类的class文件,读取进方法区,然后通过一系列的流程,来实现了解,认识某个类型。
 *      3.类加载读取class文件进方法区的手段是通过I/O流。I/O交互的形式最大的问题是慢
 *
 *
 *      思考：
 *          1.如果一个程序在启动的时候，就无脑类加载程序中的所有类。
 *              那么就会导致程序的启动非常慢，程序的执行效率很低
 *          所以在实际的JVM类加载机制设计中，类加载是懒加载的，只有当某个类必须要使用
 *              必须要类加载时，不类加载已经不行了，才会对这个类进行类加载。
 *              如果暂时用不到一个类，就不会管这个类，不会类加载它。
 *
 *          2.创建某个类的对象，能不能不类加载它？
 *              肯定不行
 *          3.创建某个类的对象，肯定需要类加载。类加载是在创建对象前还是后？
 *              肯定是在前面
 *          4.既然类加载要在创建对象之前进行，那么创建某个类的对象，会不会触发这个类类加载？
 *              肯定会，创建某个类的对象，一定会触发类加载。
 *
 *
 *          5.在Java中，我们把Java代码中一定会触发某个类类加载的场景，称之为类加载的时机。
 *              代码中一旦出现类加载的时机，就一定会触发这个类的类加载。
 *              相对的，如果没有出现类加载的时机，就一定不类加载某个类。
 *              目前我们已知的类加载的时机：
 *                  1.new对象，一定触发创建对象的类的类加载
 *                  2.启动某个类的main方法，一定触发该类的类加载。
 *              注：
 *                  代码一旦执行到类加载的时机时，会先完成类加载，再去做类加载时机的操作。
 *
 *
 *         6.某个类的类加载,在程序的某一次运行过程中,最多有几次呢?
 *              要么就不类加载某个类,不然在程序的某一次运行过程中,最多只有一次.
 *              如果代码运行到这里之前,已经由于别的原因,已经类加载一次了,就不会再次类加载了!!
 *              类加载某个类,最多只有一次,不可能出现两次.
 *
 *
 * @since 15:52
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    // 启动main方法,会触发Demo类的类加载,Demo类类加载完毕后,才能启动main方法
    public static void main(String[] args) {
        // 创建Student对象,会触发Student类的类加载,Student类类加载完毕后,才能开始创建Student对象
        Student s = new Student();

        // 创建Demo类对象,按理说应该触发类加载,但是这里不会再次类加载Demo了.因为启动main方法,已经类加载Demo了
        // 类加载只有一次
        Demo d = new Demo();
    }
}

class Student{}